package com.shanshan.crowd.controller;

import com.shanshan.crowd.api.MySQLRemoteService;
import com.shanshan.crowd.api.RedisRemoteService;
import com.shanshan.crowd.constant.CrowdConstant;
import com.shanshan.crowd.entity.po.MemberPO;
import com.shanshan.crowd.entity.vo.MemberLoginVO;
import com.shanshan.crowd.entity.vo.MemberVO;
import com.shanshan.crowd.util.CrowdUtil;
import com.shanshan.crowd.util.ResultEntity;
import com.shanshan.crowd.util.SMSUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpSession;
import javax.websocket.Session;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @Description
 * @ClassName MemberController
 * @Author 山山大魔王
 * @Date 2022/7/29 15:52
 * @Version 1.0
 */
@Controller
public class MemberController {

    @Autowired
    private SMSUtil smsUtil;

    @Autowired
    private RedisRemoteService redisRemoteService;

    @Autowired
    private MySQLRemoteService mySQLRemoteService;

    @RequestMapping("/auth/member/logout")
    public String logout(HttpSession session){

        session.invalidate();

        return "redirect:http://localhost/";
    }

    @RequestMapping("/auth/member/do/login")
    public String login(@RequestParam("loginacct") String loginacct,
                        @RequestParam("userpswd") String userpswd,
                        HttpSession session){
        // 1.调用远程接口根据登录账号查询MemberPO对象
        ResultEntity<MemberPO> resultEntity = mySQLRemoteService.getMemberPOByLoginAcctRemote(loginacct);

        if (ResultEntity.FAILED.equals(resultEntity.getOperationResult())) {

            session.setAttribute(CrowdConstant.ATTR_NAME_MESSAGE, resultEntity.getOperationMessage());

            return "member-login";
        }

        MemberPO memberPO = resultEntity.getQueryData();

        if (memberPO == null){
            session.setAttribute(CrowdConstant.ATTR_NAME_MESSAGE, CrowdConstant.MESSAGE_LOGIN_FAILED);
            return "member-login";
        }

        // 2.比较密码
        String userpswdDataBase = memberPO.getUserpswd();

        String userpswdForm = userpswd;

        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

        boolean matcheResult = passwordEncoder.matches(userpswdForm, userpswdDataBase);

        if (!matcheResult){
            session.setAttribute(CrowdConstant.ATTR_NAME_MESSAGE, CrowdConstant.MESSAGE_LOGIN_FAILED);
            return "member-login";
        }

        // 3.创建MemberLoginVO对象存入Session域
        MemberLoginVO memberLoginVO = new MemberLoginVO(memberPO.getId(), memberPO.getUsername(), memberPO.getEmail());
        session.setAttribute(CrowdConstant.ATTR_NAME_LOGIN_MEMBER,memberLoginVO);

        return "redirect:http://localhost/auth/member/to/center/page";
    }


    @RequestMapping("/auth/do/member/register")
    public String register(MemberVO memberVO, ModelMap modelMap){

        // 1.获取用户输入的手机号
        String phoneNum = memberVO.getPhoneNum();

        // 2.拼接redis中存储验证码对应的key
        String key = CrowdConstant.REDIS_CODE_PREFIX + phoneNum;
        // 3.从redis中读取key对应的value
        ResultEntity<String> resultEntity = redisRemoteService.getRedisStringValueByKeyRemote(key);
        String result = resultEntity.getOperationResult();
        // 4.检查查询操作是否有效
        if (ResultEntity.FAILED.equals(result) ) {

            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, resultEntity.getOperationMessage());

            return "member-reg";
        }
        String redisCode = resultEntity.getQueryData();

        if (redisCode == null){

            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, CrowdConstant.MESSAGE_CODE_NOT_EXISTS);

            return "member-reg";
        }

        // 5.如果能够查询到value则进行比较表单验证码和redis验证码


        String formcode = memberVO.getCode();

        if (!Objects.equals(formcode, redisCode)) {

            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, CrowdConstant.MESSAGE_CODE_INVALID);

            return "member-reg";
        }

        // 6.如果验证码一致，则从redis删除
        ResultEntity<String> removeResultEntity = redisRemoteService.removeRedisKeyRemote(key);
        // 分布式事务可以处理删除失败的操作

        // 7.执行密码加密
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

        String userpswdBeforeEncode = memberVO.getUserpswd();

        String userpswdAfterEncode = passwordEncoder.encode(userpswdBeforeEncode);

        memberVO.setUserpswd(userpswdAfterEncode);

        // 8.执行保存
        // ①创建MenberPO对象
        MemberPO memberPO = new MemberPO();

        // ②复制属性
        BeanUtils.copyProperties(memberVO, memberPO);

        // ③调用远程方法
        ResultEntity<String> saveResultEntity = mySQLRemoteService.saveMember(memberPO);

        if (ResultEntity.FAILED.equals(saveResultEntity.getOperationResult())){

            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, saveResultEntity.getOperationMessage());

            return "member-reg";

        }
        // 重定向到登录页，防止表单重复提交
        return "redirect:http://localhost/auth/member/to/login/page";
    }


    @RequestMapping("/auth/member/send/short/message.json")
    @ResponseBody
    public ResultEntity<String> sendMessage(@RequestParam("phoneNum") String phoneNum){
        // 1.生成随机6位数字验证码
        String code = CrowdUtil.randomCode();
        // 2.发送短信
        String minute = "5";
        ResultEntity<String> sendMessageResultEntity = smsUtil.sendCodeByShortMessage(phoneNum, code, minute);

        // 3.判断短信发送结果
        if (ResultEntity.SUCCESS.equals(sendMessageResultEntity.getOperationResult())){
            // 4.如果发送成功，则将验证码存入Redis
            String key = CrowdConstant.REDIS_CODE_PREFIX + phoneNum;
            int time = 5;
            ResultEntity<String> saveCodeResultEntity = redisRemoteService.setRedisKeyValueRemoteWithTimeout(key, code, time, TimeUnit.MINUTES);

            if (ResultEntity.SUCCESS.equals(saveCodeResultEntity.getOperationResult())){
                return ResultEntity.successWithoutData();
            }else {
                return saveCodeResultEntity;
            }
        }else {
            return sendMessageResultEntity;
        }
    }
}
